


/*****************************************************
	SPI.h Joe Pardue October 29, 2010

	REVISION DETAILS IN SPI.H


******************************************************/

// I HATE LICENSES LIKE THIS >>BUT<< I've been told that without
// the license then the work is automatically copyrighted in my name
// since my purpose is to educate (and learn), I want the code to be 
// used by whoever wants to use it to learn something. If you like it, 
// then visit my website www.smileymicros.com and buy something.

/*
 *  BSD License
 *  -----------
 *
 *  Copyright (c) 2008, Smiley Micros, All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  - Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer. 
 *   
 *  - Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution. 
 *   
 *  - Neither the name of the Smiley Micros nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission. 
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 */

// And to further cover my butt, let me add that if you use this software
// it will destroy whatever machine you use it on and kill anyone in a one 
// kilometer radius. So don't even consider using it for any reason whatsoever!

/*****************************************************
 	SPI.h provides headers for a library of SPI  
	functions for four types of SPI:

		Software SPI
		Hardware SPI
		USI SPI
		USART SPI
	
******************************************************/

#ifndef SPI_H
#define SPI_H

#include <avr/io.h>
#include "..\device\device.h" // defines device	

/************************************************************/
/*!	
	\def DOXYGEN
	Doxygen has a problem with the #if statements when the
	required define is in another file, so we will add a 
	special section just for Doxygen. Remove the comment '//'
	to define DOXYGEN before running Doxygen. Make sure the
	'//' is back in place before compiling the code.
*/
/************************************************************/
#define DOXYGEN	
	
/*****************************************************
******************************************************
	TODO: EXPLAIN USING MULTIPLE SPI OF VARYING TYPES
*******************************************************
******************************************************/


/* ********************************************************** */


/*****************************************************
	Define number of SPI 
******************************************************/
#define SPI0
//#define SPI1
//#define SPIx // place holder

#if defined (SPI0)
/*****************************************************
******************************************************
	SPI0
*******************************************************
******************************************************/

/*****************************************************
	Declare SPI0 function
******************************************************/
void spi0_init_master(void);
uint8_t spi0_master_rw8(uint8_t to_slave);
uint16_t spi0_master_rw16(uint16_t to_slave);

/*****************************************************
	Define SPI0 type
******************************************************/
//#define SPI0_SOFT
#define SPI0_HARD


#if defined (SPI0_SOFT)
/*****************************************************
	Software SPI
******************************************************/
private void spi0_soft_init_master(void);
uint8_t spi0_soft_master_rw8(uint8_t to_slave);
uint16_t spi0_soft_master_rw16(uint16_t to_slave);


/************************************************************/
/*!	
	\def MOSI_PORT
	Defines the MOSI port
	\def MOSI_PORT_PIN
	Defines the MOSI port and pin number
	\def MOSI_DDR
	Defines the MOSI Data Direction Register
	\def MOSI_PORT_PINS
	Defines the MOSI port pins register

	\def MISO_PORT
	Defines the MiSI port
	\def MISO_PORT_PIN
	Defines the MISI port and pin number
	\def MISO_DDR
	Defines the MISI Data Direction Register
	\def MISO_PORT_PINS
	Defines the MISI port pins register

	\def SCLK_PORT
	Defines the SCLK port
	\def SCLK_PORT_PIN
	Defines the SCLK port and pin number
	\def SCLK_DDR
	Defines the SCLK Data Direction Register

	\def SS_PORT
	Defines the SCLK port
	\def SS_PORT_PIN
	Defines the SCLK port and pin number
	\def SS_DDR
	Defines the SS Data Direction Register
*/
/************************************************************/
// Define ports, pins, and data direction registers for set up
#define MOSI_PORT PORTB
#define MOSI_PORT_PIN  PORTB3
#define MOSI_DDR  DDRB
#define MOSI_PORT_PINS PINB

#define MISO_PORT PORTB
#define MISO_PORT_PIN  PORTB4
#define MISO_DDR  DDRB
#define MISO_PORT_PINS PINB

#define SCLK_PORT PORTB
#define SCLK_PORT_PIN PORTB5
#define SCLK_DDR DDRB

#define SS_PORT PORTB
#define SS_PORT_PIN  PORTB2
#define SS_DDR  DDRB


/************************************************************/
/*!	
	\brief Moved bitwise operations to macros to 
	help keep folks heads from exploding.

	\def spi_soft_clear_ss() SS_PORT &= ~(1<<SS_PORT_PIN)
	Defines a macro to clear the slave select pin.
	\def spi_soft_set_ss() SS_PORT |= (1<<SS_PORT_PIN) 
	Defines a macro to set the slave select pin.
	\def spi_soft_set_mosi_bit() MOSI_PORT |= (1<<MOSI_PORT_PIN)
	Defines a macro to set the MOSI bit for output
	\def spi_soft_clear_mosi_bit() MOSI_PORT &= ~(1<<MOSI_PORT_PIN)
	Defines a macro to clear the MOSI bit for output
	\def is_bit_set(myVar, i) (!!(myVar & (1 << i)))
	Defines a macro to return 1 if a bit is set or 0 if not
*/
/************************************************************/
// Move bitwise operations to macros to 
// help keep folks heads from exploding
#define spi_soft_clear_ss() SS_PORT &= ~(1<<SS_PORT_PIN)
#define spi_soft_set_ss() SS_PORT |= (1<<SS_PORT_PIN) 
#define spi_soft_set_mosi_bit() MOSI_PORT |= (1<<MOSI_PORT_PIN)
#define spi_soft_clear_mosi_bit() MOSI_PORT &= ~(1<<MOSI_PORT_PIN)
#define is_bit_set(myVar, i) (!!(myVar & (1 << i)))

// Return the data pin state
uint8_t spi_soft_get_miso_bit(void);

// Return the data pin state
uint8_t spi_soft_get_miso_pin(void);

// Turn the clock line 0 to 1
void spi_soft_toggle_sclk(void);

// Initialize the SPI I/O pins
void spi_soft_setup_pins(void);


#elif defined (SPI0_HARD)
/*****************************************************
	Hardware SPI
******************************************************/
void spi0_hard_init_master(void);
uint8_t spi0_hard_master_rw8(uint8_t to_slave);
uint16_t spi0_hard_master_rw16(uint16_t to_slave);

/************************************************************/
/*!	
	\def spi_hard_clear_ss()
	Defines a macro to clear the hardware slave select pin
	\def spi_hard_set_ss()
	Defines a macro to set the hardware slave select pin
*/
/************************************************************/
#define spi_hard_clear_ss() (SS_HARDWARE_PORT &= ~(1<<SS_HARDWARE_PIN))
#define spi_hard_set_ss() (SS_HARDWARE_PORT |= (1<<SS_HARDWARE_PIN)) 

/************************************************************/
/*!	
	\note Set up SPI hardware pins. The actual port and pin numbers, shown here with x 
	are selected by device specific definitions.

	\def MOSI_HARDWARE_PIN
	Defines the MOSI port and pin number
	\def MOSI_HARDWARE_DDR
	Defines the MOSI Data Direction Register

	\def MISO_HARDWARE_PIN
	Defines the MISI port and pin number
	\def MISO_HARDWARE_DDR
	Defines the MISI Data Direction Register

	\def SCLK_HARDWARE_PIN
	Defines the SCLK port and pin number
	\def SCLK_HARDWARE_DDR
	Defines the SCLK Data Direction Register

	\def SS_HARDWARE_PORT
	Defines the SCLK port
	\def SS_HARDWARE_PIN
	Defines the SCLK port and pin number
	\def SS_HARDWARE_DDR
	Defines the SS Data Direction Register
*/
/************************************************************/
#if defined (DOXYGEN)
#define MOSI_HARDWARE_PIN PORTxx
#define MOSI_HARDWARE_DDR DDBx
#define MISO_HARDWARE_PIN PORTxx
#define MISO_HARDWARE_DDR DDxx
#define SCLK_HARDWARE_PIN PORTxx
#define SCLK_HARDWARE_DDR DDxx
#define SS_HARDWARE_PORT PORTB
#define SS_HARDWARE_PIN PORTB4
#define SS_HARDWARE_DDR DDB4

#else

#if defined (Butterfly)
#define MOSI_HARDWARE_PIN PORTB2
#define MOSI_HARDWARE_DDR DDB2
#define MISO_HARDWARE_PIN PORTB3
#define MISO_HARDWARE_DDR DDB3
#define SCLK_HARDWARE_PIN PORTB1
#define SCLK_HARDWARE_DDR DDB1
#define SS_HARDWARE_PORT PORTB
#define SS_HARDWARE_PIN PORTB4
#define SS_HARDWARE_DDR DDB4

#elif defined (Arduino) | (ATmega328)
#define MOSI_HARDWARE_PIN PORTB3
#define MOSI_HARDWARE_DDR DDB3
#define MISO_HARDWARE_PIN PORTB4
#define MISO_HARDWARE_DDR DDB4
#define SCLK_HARDWARE_PIN PORTB5
#define SCLK_HARDWARE_DDR DDB5
#define SS_HARDWARE_PORT PORTB
#define SS_HARDWARE_PIN PORTB2
#define SS_HARDWARE_DDR DDB2

#elif defined (BeAVR40) | (ATmega644)
#define MOSI_HARDWARE_PIN PB5
#define MOSI_HARDWARE_DDR DDB5
#define MISO_HARDWARE_PIN PB4
#define MISO_HARDWARE_DDR DDB4
#define SCLK_HARDWARE_PIN PB7
#define SCLK_HARDWARE_DDR DDB7
#define SS_HARDWARE_PIN PB6
#define SS_HARDWARE_DDR DDB6

#else
	#error "no SPI pins declared"
#endif

#endif // select for Doxygen

#elif defined (SPI0_USI)
/*****************************************************
	USI SPI
******************************************************/

#elif defined (SPI0_USART)
/*****************************************************
	USART SPI
******************************************************/

//#else
//   #error "no SPI0 type declared"
#endif

//#else
//   #error "no SPI0 number declared"
#endif // SPI0




#if defined (SPI1)
/*****************************************************
******************************************************
	SPI1
*******************************************************
******************************************************/

/*****************************************************
	Define SPI1 type
******************************************************/
#define SPI1_SOFT
//#define SPI1_HARD
//#define SPI1_USI
//#define SPI1_USART

/*****************************************************
	Declare SPI1 function
******************************************************/
void spi1_initmaster(void);
//void spi1_initslave(void);
void spi1_put(uint8_t);
uint8_t spi1_get(void);
//void spi1_wait(void);

//Now allow for SPI1 for each type


#if defined (SPI1_SOFT)
/*****************************************************
	Software SPI
******************************************************/

// Define ports, pins, and data direction registers for set up
#define MOSI_PORT PORTB
#define MOSI_PORT_PIN  PORTB2
#define MOSI_DDR  DDRB
#define MOSI_PORT_PINS PINB

#define MISO_PORT PORTB
#define MISO_PORT_PIN  PORTB1
#define MISO_DDR  DDRB
#define MISO_PORT_PINS PINB

#define SCLK_PORT PORTD
#define SCLK_PORT_PIN PORTD7
#define SCLK_DDR DDRD

#define SS_PORT PORTB
#define SS_PORT_PIN  PORTB0
#define SS_DDR  DDRB


// Move bitwise operations to macros to 
// help keep folks heads from exploding
#define spi_soft_clear_ss() SS_PORT &= ~(1<<SS_PORT_PIN)
#define spi_soft_set_ss() SS_PORT |= (1<<SS_PORT_PIN) 
#define spi_soft_set_mosi_bit() MOSI_PORT |= (1<<MOSI_PORT_PIN)
#define spi_soft_clear_mosi_bit() MOSI_PORT &= ~(1<<MOSI_PORT_PIN)

#define is_bit_set(myVar, i) (!!(myVar & (1 << i)))

// Return the data pin state
uint8_t spi_soft_get_miso_bit(void);

// Return the data pin state
uint8_t spi_soft_get_miso_pin(void);

// Turn the clock line 0 to 1
void spi_soft_toggle_sclk(void);

// Initialize the SPI I/O pins
void spi_soft_setup_pins(void);


#elif defined (SPI1_HARD)
/*****************************************************
	Hardware SPI
******************************************************/


#elif defined (SPI1_USI)
/*****************************************************
	USI SPI
******************************************************/

// You have to set your own slave select
#define SS_PORT PORTD
#define SS_PORT_PIN PORTD7
#define SS_DDR DDRD

#elif defined (SPI0_USART)
/*****************************************************
	USART SPI
******************************************************/

//#else
//   #error "no SPI1 type declared"
#endif

//#else
//   #error "no SPI1 number declared"
#endif // SPI1





#if defined (SPIx)
/*****************************************************
******************************************************
	SPIx
*******************************************************
******************************************************/

/*****************************************************
	Define SPIx type
******************************************************/
#define SPIx_SOFT
//#define SPIx_HARD
//#define SPIx_USI
//#define SPIx_USART

/*****************************************************
	Declare SPIx function
******************************************************/
void spix_initmaster(void);
//void spix_initslave(void);
void spix_put(uint8_t);
uint8_t spix_get(void);
//void spix_wait(void);

//Now allow for SPIx for each type


#if defined (SPIx_SOFT)
/*****************************************************
	Software SPx
******************************************************/

// Define ports, pins, and data direction registers for set up
#define MOSI_PORT PORTB
#define MOSI_PORT_PIN  PORTB2
#define MOSI_DDR  DDRB
#define MOSI_PORT_PINS PINB

#define MISO_PORT PORTB
#define MISO_PORT_PIN  PORTB1
#define MISO_DDR  DDRB
#define MISO_PORT_PINS PINB

#define SCLK_PORT PORTD
#define SCLK_PORT_PIN PORTD7
#define SCLK_DDR DDRD

#define SS_PORT PORTB
#define SS_PORT_PIN  PORTB0
#define SS_DDR  DDRB


// Move bitwise operations to macros to 
// help keep folks heads from exploding
#define spi_soft_clear_ss() SS_PORT &= ~(1<<SS_PORT_PIN)
#define spi_soft_set_ss() SS_PORT |= (1<<SS_PORT_PIN) 
#define spi_soft_set_mosi_bit() MOSI_PORT |= (1<<MOSI_PORT_PIN)
#define spi_soft_clear_mosi_bit() MOSI_PORT &= ~(1<<MOSI_PORT_PIN)

#define is_bit_set(myVar, i) (!!(myVar & (1 << i)))

// Return the data pin state
uint8_t spi_soft_get_miso_bit(void);

// Return the data pin state
uint8_t spi_soft_get_miso_pin(void);

// Turn the clock line 0 to 1
void spi_soft_toggle_sclk(void);

// Initialize the SPI I/O pins
void spi_soft_setup_pins(void);


#elif defined (SPIx_HARD)
/*****************************************************
	Hardware SPI
******************************************************/


#elif defined (SPIx_USI)
/*****************************************************
	USI SPI
******************************************************/


#elif defined (SPIx_USART)
/*****************************************************
	USART SPI
******************************************************/

//#else
//   #error "no SPIx type declared"
#endif
//#else
//   #error "no SPIx number declared"
#endif // SPIx















//#define SPI_SOFT

//#if defined (SPI_SOFT)

/*****************************************************
******************************************************
	TODO: EXPLAIN SOFTWARE SPI
*******************************************************
******************************************************/

/*****************************************************
	Software SPI
******************************************************/

// Define ports, pins, and data direction registers for set up
/*#define MOSI_PORT PORTB
#define MOSI_PORT_PIN  PORTB2
#define MOSI_DDR  DDRB
#define MOSI_PORT_PINS PINB

#define MISO_PORT PORTB
#define MISO_PORT_PIN  PORTB1
#define MISO_DDR  DDRB
#define MISO_PORT_PINS PINB

#define SCLK_PORT PORTD
#define SCLK_PORT_PIN PORTD7
#define SCLK_DDR DDRD

#define SS_PORT PORTB
#define SS_PORT_PIN  PORTB0
#define SS_DDR  DDRB


// Move bitwise operations to macros to 
// help keep folks heads from exploding
#define spi_soft_clear_ss() SS_PORT &= ~(1<<SS_PORT_PIN)
#define spi_soft_set_ss() SS_PORT |= (1<<SS_PORT_PIN) 
#define spi_soft_set_mosi_bit() MOSI_PORT |= (1<<MOSI_PORT_PIN)
#define spi_soft_clear_mosi_bit() MOSI_PORT &= ~(1<<MOSI_PORT_PIN)

#define is_bit_set(myVar, i) (!!(myVar & (1 << i)))

// Return the data pin state
uint8_t spi_soft_get_miso_bit(void);

// Return the data pin state
uint8_t spi_soft_get_miso_pin(void);

// Turn the clock line 0 to 1
void spi_soft_toggle_sclk(void);

// Initialize the SPI I/O pins
void spi_soft_setup_pins(void);


#elif defined (SPI_HARD)*/
/*****************************************************
******************************************************
	TODO: EXPLAIN SOFTWARE SPI
*******************************************************
******************************************************/

/*****************************************************
	Hardware SPI
******************************************************/


//#elif defined (SPI_USI)
/*****************************************************
******************************************************
	TODO: EXPLAIN USI SPI
*******************************************************
******************************************************/

/*****************************************************
	USI SPI
******************************************************/


//#elif defined (SPI_HARD)
/*****************************************************
******************************************************
	TODO: EXPLAIN HARDWARE SPI
*******************************************************
******************************************************/

/*****************************************************
	Hardware SPI
******************************************************/


//#elif defined (SPI_USART)
/*****************************************************
******************************************************
	TODO: EXPLAIN USART SPI
*******************************************************
******************************************************/

/*****************************************************
	USART SPI
******************************************************/

//#else
 //  #error "no SPI type declared"
//#endif




#endif // SPI_H
